package 可视化算法.基础动画升级;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import static 可视化算法.基础动画升级.AlgoVisHelper.*;

/**
 * @author MT
 * 算法可视化中的MVC
 * @date 2019-11-29 10:03
 */
public class AlgoVisualizer {

    /**
     * 一些圆
     */
    private Circle[] circles;

    /**
     * 画板
     */
    private AlgoFrame frame;


    /**
     * 动画是否在执行
     */
    private boolean isAnimated = true;

    /**
     * 颜色选项
     */
    private Color[] colors = {
            Red, Pink, Purple, DeepPurple, Indigo,
            Blue, LightBlue, Cyan, Teal, Green,
            LightGreen, Lime, Yellow, Amber, Orange,
            DeepOrange, Brown, Grey, BlueGrey, Black, White
    };


    public AlgoVisualizer(int sceneWidth, int sceneHeight, int N) {
        // 圆的半径
        int R = 50;
        this.circles = new Circle[N];
        for (int i = 0; i < N; i++) {
            // 生成0~1之间的随机数x,y，当做圆心坐标
            int x = (int) (Math.random() * (sceneWidth - 2 * R)) + R;
            int y = (int) (Math.random() * (sceneHeight - 2 * R)) + R;

            // 生成0~5的随机数速度
            int vx = (int) (Math.random() * 11) - 3;
            int vy = (int) (Math.random() * 11) - 3;
            Color color = colors[(int) (Math.random() * 20)];

            this.circles[i] = new Circle(i, x, y, R, vx, vy, color);
        }
        EventQueue.invokeLater(() -> {
            this.frame = new AlgoFrame("基础动画之动态圆", sceneWidth, sceneHeight);
            // 添加键盘事件
            this.frame.addKeyListener(new AlgoKeyListener());
            // 添加鼠标事件
            this.frame.addMouseListener(new AlgoMouseListener());
            new Thread(() -> {
                this.run();
            }).start();
        });
    }

    /**
     * 动画逻辑
     */
    private void run() {
        while (true) {
            //绘制数据
            this.frame.render(this.circles);
            AlgoVisHelper.pause(50);
            //更新数据
            if (isAnimated) {
                // 根据状态是否执行动画
                for (Circle circle : this.circles) {
                    circle.move(0, 0, frame.getCanvasWidth(), frame.getCanvasHeight(), this.circles);
                }
            }
        }
    }


    /**
     * 键盘事件内部类
     * implements KeyListener 必需实现接口所有方法，不方便
     * 所以使用 继承keyAdapter
     */
    private class AlgoKeyListener extends KeyAdapter {

        /**
         * 键盘按下" "空格改变动画状态
         *
         * @param event
         */
        @Override
        public void keyReleased(KeyEvent event) {
            if (" ".charAt(0) == event.getKeyChar()) {
                isAnimated = !isAnimated;
            }
        }
    }

    /**
     * 鼠标事件内部类
     * 创建在frame上
     */
    private class AlgoMouseListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent event) {
            // 打印鼠标点击事件位置
            // System.out.println(event.getPoint());

            // 位移鼠标传进来的点，使其成为窗口坐标
            event.translatePoint(0, -(frame.getBounds().height - frame.getCanvasHeight()));

            for (Circle circle : circles) {
                // 判断点坐标是否在圆内
                if (circle.contain(event.getPoint())) {
                    circle.isFilled = !circle.isFilled;
                }
            }
        }
    }
}
